package main

import (
	"fmt"
	"github.com/hyperledger/fabric-chaincode-go/shim"
	"github.com/hyperledger/fabric-protos-go/peer"
	"encoding/json"
)

type SupplyChainCode struct {

}


type RentingProductInfo struct {
	RentingID        string    `json:"renting_id"`         // 统一编码
	RentingProductInfo ProductInfo `json:"renting_house_info"` // 房屋信息
	RentingManufacturerInfo  ManufacturerInfo  `json:"renting_area_info"`  //区域信息
	RentingAgencyInfo AgencyInfo `json:"renting_order_info"` //订单信息
}




type ProductInfo struct {
	FoodMaterial   string `json:"food_material"`    // 食材种类
	ProduceDate    string `json:"produce_date"`     // 生产日期
	ProcessTech    string `json:"process_tech"`     // 加工工艺
	BestBefore     string `json:"best_Before"`      // 食用期限
	ProductionDate string `json:"production_Date"`  // 出厂日期
	ProductionSold string `json:"production_sold"`  // 出售厂商
}


type ManufacturerInfo struct {
	FactoryNo         string `json:"factory_No"`         //加工厂商编号
	ProductionNo      string `json:"production_No"`      //生产序号
	ProductionCode    string `json:"production_Code"`    //货号
	ProcessCriterion          string `json:"process_Criterion"`          //加工标准
	ProductionCountry string `json:"production_Country"` //食品生产国
}


type AgencyInfo struct {
	AgencyName      string `json:"agency_Name"`       // 贸易商
	TradeDate       string `json:"trade_Date"`        // 经销时间
	TradeCountry    string `json:"trade_Country"`     // 经销国家
	AgencyBuyinTime string `json:"agency_Buyin_Time"` // 经销进货时间
	RetailName      string `json:"retail_Name"`       // 零售商
	RetailRegion    string `json:"retail_Region"`     // 零售地区
	RetailBuyinTime string `json:"retail_Buyin_Time"` // 零售进货时间

}

func (this *SupplyChainCode) Init(stub shim.ChaincodeStubInterface) peer.Response {
	fmt.Println(" ==== gongyinglian_suyuan Init ====")
	fmt.Println("000000000000000000")
	return shim.Success(nil)
}

func (this *SupplyChainCode) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
	// 获取 函数名 和 参数列表
	fn, parameters := stub.GetFunctionAndParameters()

	// 通过函数名匹配对应的链代码函数调用
	if fn == "addProductInfo" {
		return this.addProductInfo(stub,parameters)
	}else if fn =="getProductInfo"{
		return this.getProductInfo(stub,parameters)
	}else if fn =="addAgencyInfo"{
		return this.addAgencyInfo(stub,parameters)
	}else if fn == "getAgencyInfo"{
		return this.getAgencyInfo(stub,parameters)
	}else if fn == "addManufacturerInfo"{
		return this.addManufacturerInfo(stub,parameters)
	}else if fn=="getManufacturerInfo"{
		return this.getManufacturerInfo(stub,parameters)
	}

	// 没有任何函数被匹配到，返回错误消息
	fmt.Println("==== fn = ",fn)
	return shim.Error("Received unknow function invocation")
}


func (this *SupplyChainCode) addProductInfo(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	// 定义一个信息结构体
	var ProductInfos RentingProductInfo

	if len(args) !=7{
		return shim.Error("Incorrect number oof arguments.")
	}

	ProductInfos.RentingID = args[0]
	if ProductInfos.RentingID == ""{
		return shim.Error("RentingId can't be empty.")
	}

	ProductInfos.RentingProductInfo.FoodMaterial = args[1]
	ProductInfos.RentingProductInfo.ProduceDate = args[2]
	ProductInfos.RentingProductInfo.ProcessTech = args[3]
	ProductInfos.RentingProductInfo.BestBefore = args[4]
	ProductInfos.RentingProductInfo.ProductionDate = args[5]
	ProductInfos.RentingProductInfo.ProductionSold = args[6]

	ProductInfosJsonBytes,err := json.Marshal(ProductInfos)
	if err!=nil{
		return shim.Error(err.Error())
	}

	err = stub.PutState(ProductInfos.RentingID,ProductInfosJsonBytes)
	if err !=nil{
		return shim.Error(err.Error())
	}

	return shim.Success([]byte("ok"))
}


func (this *SupplyChainCode) getProductInfo(stub shim.ChaincodeStubInterface, args []string) peer.Response{
	// 判断参数个数
	if len(args)!=1{
		return shim.Error("Incorrect number of arguments.")
	}
	// 获取唯一标识码
	rentingID := args[0]

	// 获得查询结果迭代器
	resultItreator ,err := stub.GetHistoryForKey(rentingID)
	if err!=nil{
		return shim.Error(err.Error())
	}

	// 释放迭代器资源
	defer resultItreator.Close()

	var rentProductInfo ProductInfo

	// 使用迭代器遍历查询结果集
	for resultItreator.HasNext(){
		var ProductInfos RentingProductInfo
		// 取一条结果
		response,err := resultItreator.Next()
		if err !=nil{
			return shim.Error(err.Error())
		}

		err = json.Unmarshal(response.Value,&ProductInfos)
		if err!=nil{
			return shim.Error(err.Error())
		}

		if ProductInfos.RentingProductInfo.ProduceDate!=""{
			rentProductInfo = ProductInfos.RentingProductInfo
			continue
		}
	}

	jsonAsBytes ,err := json.Marshal(rentProductInfo)
	if err!=nil{
		return shim.Error(err.Error())
	}

	// 返回数据查询结果
	return shim.Success(jsonAsBytes)
}


func (this *SupplyChainCode) addManufacturerInfo(stub shim.ChaincodeStubInterface, args []string) peer.Response{
	var ProductInfos RentingProductInfo

	if len(args) != 6 {
		return shim.Error("Add estate incorrect number of arguments.")
	}

	ProductInfos.RentingID = args[0]
	if ProductInfos.RentingID == "" {
		return shim.Error("RentingID can not be empty.")
	}

	ProductInfos.RentingManufacturerInfo.FactoryNo = args[1]
	ProductInfos.RentingManufacturerInfo.ProductionNo = args[2]
	ProductInfos.RentingManufacturerInfo.ProductionCode = args[3]
	ProductInfos.RentingManufacturerInfo.ProcessCriterion = args[4]
	ProductInfos.RentingManufacturerInfo.ProductionCountry = args[5]

	//if ProductInfos.RentingManufacturerInfo.FactoryNo == "" {
	//	return shim.Error("Area's num not be empty")
	//}

	ManufacturerInfosJsonBytes, err := json.Marshal(ProductInfos)

	if err != nil {
		return shim.Error(err.Error())
	}
	err = stub.PutState(ProductInfos.RentingID, ManufacturerInfosJsonBytes)
	if err != nil {
		return shim.Error(err.Error())
	}
	fmt.Printf("ADD SUCCESSFULLY")
	return shim.Success(nil)
}


func (this *SupplyChainCode) getManufacturerInfo(stub shim.ChaincodeStubInterface, args []string) peer.Response{
	if len(args) !=1{
		return shim.Error("Incorrent number of arguments.")
	}
	rentingID := args[0]

	resultsIterator,err := stub.GetHistoryForKey(rentingID)
	if err!=nil{
		return shim.Error(err.Error())
	}

	defer resultsIterator.Close()

	var rentManufacturerInfo ManufacturerInfo

	for resultsIterator.HasNext(){
		var ProductInfos RentingProductInfo
		response,err := resultsIterator.Next()
		if err!=nil{
			return shim.Error(err.Error())
		}

		json.Unmarshal(response.Value,&ProductInfos)

		if ProductInfos.RentingManufacturerInfo.FactoryNo!=""{

			rentManufacturerInfo =ProductInfos.RentingManufacturerInfo
			fmt.Println("************* rentManufacturerInfo = ",rentManufacturerInfo)
			continue
		}
	}
	jsonAsBytes,err := json.Marshal(rentManufacturerInfo)
	if err !=nil{
		return shim.Error(err.Error())
	}

	return shim.Success(jsonAsBytes)
}


func (this *SupplyChainCode) addAgencyInfo(stub shim.ChaincodeStubInterface, args []string) peer.Response{
	var ProductInfos RentingProductInfo

	if len(args)!=8{
		return shim.Error("Incorrect number of arguments.")
	}

	ProductInfos.RentingID = args[0]
	if ProductInfos.RentingID ==""{
		return shim.Error("RentingID can not be empty.")
	}

	ProductInfos.RentingAgencyInfo.AgencyName = args[1]
	ProductInfos.RentingAgencyInfo.TradeDate = args[2]
	ProductInfos.RentingAgencyInfo.TradeCountry= args[3]
	ProductInfos.RentingAgencyInfo.AgencyBuyinTime = args[4]
	ProductInfos.RentingAgencyInfo.RetailName = args[5]
	ProductInfos.RentingAgencyInfo.RetailRegion = args[6]
	ProductInfos.RentingAgencyInfo.RetailBuyinTime = args[7]

	fmt.Println("^^^^^^^^ = ",ProductInfos.RentingAgencyInfo)
	ProductInfosJsonBytes,err := json.Marshal(ProductInfos)
	if err!=nil{
		return shim.Error(err.Error())
	}


	err = stub.PutState(ProductInfos.RentingID,ProductInfosJsonBytes)
	if err!=nil{
		return shim.Error(err.Error())
	}

	return shim.Success([]byte("ok"))
}


func (this *SupplyChainCode) getAgencyInfo(stub shim.ChaincodeStubInterface, args []string) peer.Response{
	var AgencyInfos []AgencyInfo
	if len(args)!=1{
		return shim.Error("Incorrect number of arguments.")
	}

	rentingID := args[0]

	resultsIterator,err:=stub.GetHistoryForKey(rentingID)
	if err!=nil{
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	var rentAgencyInfo AgencyInfo

	for resultsIterator.HasNext(){
		var ProductInfos RentingProductInfo
		response,err := resultsIterator.Next()
		if err!=nil{
			return shim.Error(err.Error())
		}

		json.Unmarshal(response.Value,&ProductInfos)
		if ProductInfos.RentingAgencyInfo.AgencyName!=""{
			AgencyInfos = append(AgencyInfos,ProductInfos.RentingAgencyInfo)
			continue
		}
	}

	fmt.Println("=============",rentAgencyInfo)
	fmt.Println("2222222222222:",AgencyInfos)
	jsonAsBytes,err :=json.Marshal(AgencyInfos)


	if err!=nil{
		return shim.Error(err.Error())
	}
	return shim.Success(jsonAsBytes)
}

func main() {
	err := shim.Start(new(SupplyChainCode))
	if err != nil {
		fmt.Println("Error starting food chaincode :%s", err)
	}
}

